Micron Document
C.S.Burner πŸͺ™ ━►πŸ”₯GIT Node

Node / reticulum_mirror / MeshChatX / files / docs / en / plugins.md

Displaying Rendered β€’ View raw β€’ Download

docs/en/plugins.md dev (8f381c86) Text, 9.42 KB

Plugins

Plugins extend MeshChatX with extra tools, nav items, and background behaviour. They are capability-gated: a plugin only gets what you grant at install time.

Manage them from Settings β†’ Plugins. Disable every packaged plugin at startup with T383838--disable-plugins or T383838MESHCHAT_DISABLE_PLUGINS=true.

What plugins can do

β€’ Add a row on the Tools page
β€’ Add an item in the main Navigation sidebar
β€’ React to mesh events (announces, RNS link traffic)
β€’ Call narrowly declared backend managers (path table, debug log, bug reports, RNS links)
β€’ Keep a private key-value store (T383838storage: isolated)
β€’ Optionally fetch clearnet HTTP (T383838network: fetch), still subject to Privacy mode

Plugins cannot rewrite core MeshChatX. They do not get open-ended filesystem or process control unless you opt into Sideband Python plugins (see below).

Runtimes

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Runtime β”‚ Where it runs β”‚ Trust level β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Frontend JS β”‚ Browser Web Worker β”‚ Medium. Sandboxed worker, capability grants β”‚
β”‚ Backend WASM β”‚ T383838wasmtime on the server β”‚ Medium. Fuel-metered, capability-gated host β”‚
β”‚ Backend Python β”‚ In-process with MeshChatX β”‚ High. Permission-checked in-process host β”‚
β”‚ Sideband T383838*.py β”‚ In-process, flat files β”‚ Highest. Opt-in danger switch, full host access β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

A packaged plugin can ship frontend only, backend only, or both.

Install flow

T282828
Pick ZIP or .wasm file in Settings β†’ Plugins
|
--> Preview (permissions, URLs, signature, findings)
|
--> You grant or deny each capability
|
--> Optional: trust a valid signer
|
--> Install + integrity hash stored
|
--> Enable
|
--> Frontend Worker loads (if present)
--> Backend WASM / Python activates (if present)

Invalid signatures hard-block install. Unsigned packages are allowed. Present-but-broken signatures are not.

After install, MeshChatX hashes the on-disk tree. If files change outside the app, the plugin is auto-disabled as tampered.

Bundled example: Bug Reports

T383838com.meshchatx.mcx-bugs ships with MeshChatX. It adds a Bug Reports tool for sending redacted debug logs to an T383838mcx-bugs-v1 collector, or running a collector yourself.

Layout:

T282828
mcx-bugs/
plugin.json
frontend/main.js
backend/main.py
locales/en.json

Use it as the reference package when building your own.

Manifest (T383838plugin.json)

Every packaged plugin needs a root T383838plugin.json.

T282828
Tb4b4b4{
Tff7b72"id"Tb4b4b4: Ta5d6ff"com.example.my-plugin"Tb4b4b4,
Tff7b72"version"Tb4b4b4: Ta5d6ff"1.0.0"Tb4b4b4,
Tff7b72"apiVersion"Tb4b4b4: T79c0ff1Tb4b4b4,
Tff7b72"name"Tb4b4b4: Ta5d6ff"My Plugin"Tb4b4b4,
Tff7b72"description"Tb4b4b4: Ta5d6ff"Adds a custom tool."Tb4b4b4,
Tff7b72"frontend"Tb4b4b4: Tb4b4b4{
Tff7b72"entry"Tb4b4b4: Ta5d6ff"frontend/main.js"Tb4b4b4,
Tff7b72"type"Tb4b4b4: Ta5d6ff"js"
Tb4b4b4},
Tff7b72"backend"Tb4b4b4: Tb4b4b4{
Tff7b72"entry"Tb4b4b4: Ta5d6ff"backend/main.py"Tb4b4b4,
Tff7b72"type"Tb4b4b4: Ta5d6ff"python"
Tb4b4b4},
Tff7b72"i18n"Tb4b4b4: Tb4b4b4{
Tff7b72"directory"Tb4b4b4: Ta5d6ff"locales"Tb4b4b4,
Tff7b72"defaultLocale"Tb4b4b4: Ta5d6ff"en"
Tb4b4b4},
Tff7b72"contributes"Tb4b4b4: Tb4b4b4{
Tff7b72"navItems"Tb4b4b4: Tb4b4b4[
Tb4b4b4{
Tff7b72"id"Tb4b4b4: Ta5d6ff"my-plugin"Tb4b4b4,
Tff7b72"route"Tb4b4b4: Tb4b4b4{ Tff7b72"name"Tb4b4b4: Ta5d6ff"plugin-my-plugin" Tb4b4b4},
Tff7b72"icon"Tb4b4b4: Ta5d6ff"puzzle"Tb4b4b4,
Tff7b72"labelKey"Tb4b4b4: Ta5d6ff"nav"
Tb4b4b4}
Tb4b4b4],
Tff7b72"toolsPageEntries"Tb4b4b4: Tb4b4b4[
Tb4b4b4{
Tff7b72"name"Tb4b4b4: Ta5d6ff"my-plugin"Tb4b4b4,
Tff7b72"route"Tb4b4b4: Tb4b4b4{ Tff7b72"name"Tb4b4b4: Ta5d6ff"plugin-my-plugin" Tb4b4b4},
Tff7b72"icon"Tb4b4b4: Ta5d6ff"puzzle"Tb4b4b4,
Tff7b72"titleKey"Tb4b4b4: Ta5d6ff"title"Tb4b4b4,
Tff7b72"descriptionKey"Tb4b4b4: Ta5d6ff"description"
Tb4b4b4}
Tb4b4b4]
Tb4b4b4},
Tff7b72"permissions"Tb4b4b4: Tb4b4b4{
Tff7b72"hooks"Tb4b4b4: Tb4b4b4[Ta5d6ff"announce.received"Tb4b4b4],
Tff7b72"managers"Tb4b4b4: Tb4b4b4[Ta5d6ff"destinationPath.read"Tb4b4b4],
Tff7b72"storage"Tb4b4b4: Ta5d6ff"isolated"Tb4b4b4,
Tff7b72"network"Tb4b4b4: Ta5d6ff"none"
Tb4b4b4}
Tb4b4b4}


Notes:

β€’ T383838id is reverse-DNS style and must stay stable across versions
β€’ T383838apiVersion is currently T3838381
β€’ Plugin strings live in the plugin bundle (T383838locales/{locale}.json), not core T383838en.json
β€’ T383838contributes wires UI slots through the frontend registries

Permissions

Nothing is available unless it is declared in the manifest and granted in the install dialog.

Hooks

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Hook β”‚ When it fires β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ T383838announce.received β”‚ A Reticulum announce arrives β”‚
β”‚ T383838rns.link.event β”‚ Generic RNS Link traffic (T383838packet_received, T383838link_closed) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Hook events reach the UI as WebSocket T383838plugin.event frames, then into the plugin Worker.

Managers

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Manager β”‚ Purpose β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ T383838destinationPath.read β”‚ Read the Reticulum path table β”‚
β”‚ T383838debugLog.read β”‚ Read redacted debug logs β”‚
β”‚ T383838bugReport.* β”‚ Bug report / collector APIs β”‚
β”‚ T383838rnsLink.open β”‚ Open or reuse an RNS link β”‚
β”‚ T383838rnsLink.identify β”‚ Identify on a cached link β”‚
β”‚ T383838rnsLink.request β”‚ Request/response on a link β”‚
β”‚ T383838rnsLink.send β”‚ Send a raw link packet β”‚
β”‚ T383838rnsLink.close β”‚ Tear down a cached link β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Call managers from a plugin with T383838POST /api/v1/plugins/{id}/invoke and T383838method: "callManager". Details for the link transport are in RNS Link API.

Storage and network

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Permission β”‚ Effect β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ T383838storage: isolated β”‚ Private key-value store in the MeshChatX database β”‚
β”‚ T383838storage: none β”‚ No plugin storage β”‚
β”‚ T383838network: fetch β”‚ Outbound HTTP allowed (still blocked by Privacy mode when that is on) β”‚
β”‚ T383838network: none β”‚ No clearnet fetch β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Install preview also scans plugin files for external T383838http:// / T383838https:// URLs and shows them before you grant network access.

How a frontend plugin runs

T282828
Settings enable plugin
|
--> PluginHost loads /api/v1/plugins
|
--> Fetch frontend entry as text
|
--> Spawn pluginWorker.js (module Worker)
|
--> Register nav / tools contributions
|
--> Subscribe to plugin.event on /ws (if hooks granted)
|
--> Worker may invoke backend via /api/v1/plugins/{id}/invoke

The Worker talks to the host with typed messages (T383838init, T383838event, T383838request). The host never gives the Worker a raw privileged API.

How a backend plugin runs

T282828
Enable plugin
|
+--> type: wasm --> load into wasmtime, fuel + host caps
|
+--> type: python --> import entry, call activate(host)
|
--> Hooks fan out from PluginManager
|
--> invoke(method, args) for RPC from the UI Worker

Python host surface (permission-checked):

β€’ T383838host.log(message)
β€’ T383838host.call_manager(capability, args)
β€’ T383838host.storage_get(key) / T383838host.storage_set(key, value)
β€’ T383838host.network_fetch_allowed()

Packaging and signing

Distribute as:

1. ZIP with T383838plugin.json and assets
2. WASM bundle (single T383838.wasm with embedded manifest / files / optional signature)

Signature file for ZIP/dir packages: T383838meshchatx.plugin.rsg

WASM custom sections:

T282828
meshchatx.plugin --> embedded plugin.json
meshchatx.files --> embedded text assets
meshchatx.signature --> RSG over payload without this section

Canonical ZIP signing uses sorted paths and fixed 1980-01-01 mtimes. The signature file itself is excluded from the signed payload.

Sign and verify with:

T282828
python3 scripts/sign-plugin.py sign-dir ./my-plugin --identity <rnid>
python3 scripts/sign-plugin.py verify-dir ./my-plugin
python3 scripts/sign-plugin.py sign-zip ./my-plugin.zip --identity <rnid>
python3 scripts/sign-plugin.py sign-wasm ./plugin.wasm --identity <rnid>
python3 scripts/sign-plugin.py sign-py ./legacy_plugin.py --identity <rnid>

Trust status in the UI:

T282828
No .rsg present
--> Unsigned (install allowed)

Valid .rsg, signer unknown
--> Signed (you can add to Trusted Publishers)

Valid .rsg, signer in Trusted Publishers
--> Trusted

Broken / mismatched .rsg
--> Invalid (install blocked)

Sideband-compatible plugins

Legacy Sideband-style flat T383838*.py files are separate from packaged ZIP/WASM plugins.

T282828
Settings β†’ Plugins β†’ Sideband
|
--> Confirm danger prompt
|
--> Set directory of *.py files
|
--> Optional filename.py.rsg next to each script
|
--> Reload

These run in-process with full host access. They are not ZIP-permission gated. Keep the master switch off unless you trust every file in that directory.

Operator tips

β€’ Prefer signed packages from publishers you added yourself
β€’ Deny T383838network: fetch unless the plugin needs clearnet HTTP
β€’ Prefer WASM backends over Python when you can
β€’ Use T383838--disable-plugins when diagnosing weird UI or backend behaviour
β€’ Treat Sideband plugins like running arbitrary local scripts

See also

β€’ Tools and utilities for the Tools page and contribution overview
β€’ RNS Link API for T383838rnsLink.* and T383838rns.link.event
β€’ Architecture and design for the plugin runtime overview
β€’ Identities, privacy, and security for signing and Privacy mode

Served by rngit 1.3.7 - Generated in 0.03s